﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;


static class Extensions
{
    public static StringBuilder Substring(this StringBuilder stringBuild, int index, int lenght)
    {
        StringBuilder str = new StringBuilder();
        for (int i = index; i < index + lenght; ++i)
        {
            str.Append(stringBuild[i]);
        }
        return str;
    }

    private static decimal SumOfElements<T>(this IEnumerable<T> arr)
    {
        if (arr == null || !arr.GetEnumerator().MoveNext())
        {
            throw new ArgumentException("Invalid Agument In SumOfElements.");
        }
        decimal sum = 0;
        foreach (T el in arr)
        {
            sum += Convert.ToDecimal(el);
        }
        return sum;
    }
    private static decimal ProductOfElements<T>(this IEnumerable<T> arr)
    {
        if (arr == null || !arr.GetEnumerator().MoveNext())
        {
            throw new ArgumentException("Invalid Agument In ProductOfElements.");
        }
        decimal product = 1;
        foreach (T el in arr)
        {
            product *= Convert.ToDecimal(el);
        }
        return product;
    }
    private static decimal AverageOfElements<T>(this IEnumerable<T> arr)
    {
        if (!arr.GetEnumerator().MoveNext())
        {
            throw new ArgumentException("Invalid Argument in AverageOfElements.");
        }
        decimal sum = arr.SumOfElements<T>();
        return sum / arr.Count();
    }

    private static T NewMin<T>(this IEnumerable<T> arr) where T : IComparable
    {
        if (arr == null || !arr.GetEnumerator().MoveNext())
        {
            throw new ArgumentException("Invalid Agument In NewMin.");
        }
        T min = arr.First();
        foreach (T el in arr)
        {
            if (el.CompareTo(min) < 0)
            {
                min = el;
            }
        }
        return min;
    }
    private static T NewMax<T>(this IEnumerable<T> arr) where T : IComparable
    {
        if (arr == null || !arr.GetEnumerator().MoveNext())
        {
            throw new ArgumentException("Invalid Agument In NewMax.");
        }
        T max = arr.First();
        foreach (T el in arr)
        {
            if (el.CompareTo(max) == 1)
            {
                max = el;
            }
        }
        return max;
    }

    private static string FirstCapitalLetter(this string str)
    {
        if (str == null || str.Length == 0)
        {
            return str;
        }
        string firstLetter = Convert.ToString(str[0]);
        return firstLetter.ToUpper() + str.Substring(1);
    }

    
    static void Main()
    {
        StringBuilder st = new StringBuilder("123456789");
        Console.WriteLine(st.Substring(1, 5));
        List<int> l = new List<int>() { 1, 2, 3, -1, 4, 6 };
        Console.WriteLine("The sum of the elements is: {0}", l.SumOfElements<int>());
        Console.WriteLine("The product of the elements is: {0}", l.ProductOfElements<int>());
        Console.WriteLine("The average of the elements is: {0}", l.AverageOfElements<int>());
        List<string> l2 = new List<string>() { "one", "two", "three" };
        Console.WriteLine("The min is: {0}", l.NewMin<int>());
        Console.WriteLine("The max is: {0}", l.NewMax<int>());
        Console.WriteLine("The min is: {0}", l2.NewMin<string>());
        Console.WriteLine("The max is: {0}", l2.NewMax<string>());

        var listOfStudents = new[] {
                                        new { FirstName = "Go6o", LastName = "Ivanov"},
                                        new { FirstName = "Ivan", LastName = "Ivanox"},
                                        new { FirstName = "Emil", LastName = "Georgiev"},
                                        new { FirstName = "Ivan", LastName = "Petrov"},
                                        new { FirstName = "Petar", LastName = "Mihov"},
                                        new { FirstName = "Zarko", LastName = "Vidolov"}
                                    };

        var firstNameBeforeLast = from student in listOfStudents
                     where student.FirstName.CompareTo(student.LastName) < 0 
                     select student;

        foreach (var stud in firstNameBeforeLast)
        {
            Console.WriteLine(stud);
        }
        Console.WriteLine();

        var listOfStudentsWithAge = new[] {
                                        new { FirstName = "Go6o", LastName = "Ivanov", Age = 19},
                                        new { FirstName = "Ivan", LastName = "Petrov", Age = 25},
                                        new { FirstName = "Emil", LastName = "Georgiev", Age = 21},
                                        new { FirstName = "Ivan", LastName = "Ivanov", Age = 24},
                                        new { FirstName = "Petar", LastName = "Mihov", Age = 22},
                                        new { FirstName = "Zarko", LastName = "Vidolov", Age = 41}
                                    };

        var ageBetween18And24 = from student in listOfStudentsWithAge
                                where student.Age > 18 && student.Age < 24
                                select new { student.FirstName, student.LastName };

        foreach (var stud in ageBetween18And24)
        {
            Console.WriteLine(stud);
        }
        Console.WriteLine();

        var sortedListOfStudents = listOfStudents.OrderByDescending(x => x.FirstName).ThenByDescending(x => x.LastName);

        foreach (var stud in sortedListOfStudents)
        {
            Console.WriteLine(stud);
        }
        Console.WriteLine();

        List<int> listOfNumbers = new List<int>() { 2, 3, 7, 21, 42, 49, 33 };
        List<int> divisibleBy3And7 = listOfNumbers.FindAll(x => x % 3 == 0 && x % 7 == 0);

        foreach (var num in divisibleBy3And7)
        {
            Console.WriteLine(num);
        }
        Console.WriteLine();

        var divisible = from num in listOfNumbers
                        where num % 3 == 0 && num % 7 == 0
                        select num;
        foreach (var num in divisible)
        {
            Console.WriteLine(num);
        }
        Console.WriteLine();

        string foo = "zarko";
        Console.WriteLine(foo.FirstCapitalLetter());

        TextInfo info = CultureInfo.CurrentCulture.TextInfo;
        Console.WriteLine(info.ToTitleCase("алабала портокала"));
    }
}

